package org.bigdata.framework.core.redis;

import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Set;

import org.bigdata.framework.core.utils.SettingUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.xxl.conf.core.XxlConfClient;

/**
 * 封装redis 缓存服务器服务接口
 *
 * @author vimes
 *
 */
@Service(value = "redisService")
public class RedisServiceImpl implements RedisService {

    private static String redisCode = XxlConfClient.get("dal.redis.character",
            "gbk");

    private RedisServiceImpl() {

    }

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * @param key
     */
    @SuppressWarnings("unchecked")
    public long del(final String... keys) {
        return (long) redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection)
                    throws DataAccessException {
                long result = 0;
                for (int i = 0; i < keys.length; i++) {
                    result = connection.del(keys[i].getBytes());
                }
                return result;
            }
        });
    }

    /**
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(final byte[] key, final byte[] value, final long liveTime) {
        redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection)
                    throws DataAccessException {
                connection.set(key, value);
                if (liveTime > 0) {
                    connection.expire(key, liveTime);
                }
                return 1L;
            }
        });
    }

    /**
     * @param key
     * @param value
     * @param liveTime
     */
    public void set(String key, String value, long liveTime) {
        try {
            value = new String(value.getBytes(), redisCode);
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        this.set(key.getBytes(), value.getBytes(), liveTime);
    }

    /**
     * @param key
     * @param value
     */
    public void set(String key, String value) {
        this.set(key, value, 0L);
    }

    /**
     * @param key
     * @param value
     */
    public void set(byte[] key, byte[] value) {
        this.set(key, value, 0L);
    }

    /**
     * @param key
     * @return
     */
    public String get(final String key) {
        return (String) redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection)
                    throws DataAccessException {
                try {
                    return new String(connection.get(key.getBytes()), redisCode);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return "";
            }
        });
    }

    /**
     * @param pattern
     * @return
     */
    public Set keys(String pattern) {
        return redisTemplate.keys(pattern);

    }

    /**
     * @param key
     * @return
     */
    public boolean exists(final String key) {
        return (boolean) redisTemplate.execute(new RedisCallback() {
            public Boolean doInRedis(RedisConnection connection)
                    throws DataAccessException {
                return connection.exists(key.getBytes());
            }
        });
    }

    /**
     * @return
     */
    public String flushDB() {
        return (String) redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection)
                    throws DataAccessException {
                connection.flushDb();
                return "ok";
            }
        });
    }

    /**
     * @return
     */
    public long dbSize() {
        return (long) redisTemplate.execute(new RedisCallback() {
            public Long doInRedis(RedisConnection connection)
                    throws DataAccessException {
                return Long.parseLong(connection.dbSize().toString()) ;
            }
        });
    }

    /**
     * @return
     */
    public String ping() {
        return (String) redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection)
                    throws DataAccessException {

                return connection.ping();
            }
        });
    }

    @Override
    public void set(String key, Object value) {
        // TODO Auto-generated method stub
        String objectJson = JSON.toJSONString(value);
        this.set(key, objectJson, 0L);
    }

    @Override
    public <T> T getObject(final String key, Class<T> clazz) {
        // TODO Auto-generated method stub
        String value = (String) redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection)
                    throws DataAccessException {
                try {
                    return new String(connection.get(key.getBytes()), redisCode);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return "";
            }
        });
        return JSON.parseObject(value, clazz);
    }

    @Override
    public <T> List<T> getList(final String key, Class<T> clazz) {
        // TODO Auto-generated method stub
        String value = (String) redisTemplate.execute(new RedisCallback() {
            public String doInRedis(RedisConnection connection)
                    throws DataAccessException {
                try {
                    return new String(connection.get(key.getBytes()), redisCode);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                return "";
            }
        });
        return JSON.parseArray(value, clazz);
    }

}
